#-------------------------------------------------------------------------------
# Name:        Game
# Purpose:
#
# Author:      Theo
#
# Created:     10/02/2012
# Copyright:   (c) Monxcleyr Productions 2012
# Licence:     GPL v3
#-------------------------------------------------------------------------------
#!/usr/bin/env python

import pygame, sys, cPickle, zlib, os, logging
import config, key, sound, debug, options, common, world, menu, pause, stars, minigame
from ..gui import label
from ..tools import videotools
from pygame.locals import *
from . import __version__ #Import engine version


class Game:
  def __init__(self):
    # Class containing common engine variables
    logging.info('Engine Version %s' % __version__)
    self.common = common.Common()
    self.SW = self.common.reswidths[self.common.settings.res_setting] # Load up the defined resolution
    self.SH = int(self.SW / self.common.scale)
    self.size = (self.SW, self.SH)

    # The various surfaces the game will use
    self.menuS = pygame.Surface(self.common.initsize)
    self.menuS.set_colorkey((255,0,255))
    self.optionS = pygame.Surface(self.common.initsize)
    self.optionS.set_colorkey((255,0,255))
    self.gameS = pygame.Surface(self.common.initsize)
    self.gameS.set_colorkey((255,0,255))
    self.mapS = pygame.Surface(self.common.initsize)
    self.titleS = pygame.Surface(self.common.initsize)
    # Everything is draw onto preS before drawn to the screen
    self.preS = pygame.Surface((self.SW, self.SH))
    # Debug Screen so it can be drawn on top
    self.debugS = pygame.Surface(self.common.initsize, SRCALPHA)
    self.screen = pygame.display.set_mode((self.SW, self.SH), SRCALPHA|DOUBLEBUF)
    if self.common.settings.fullscreen == True:
      self.screen = pygame.display.set_mode(self.size, SRCALPHA|DOUBLEBUF|FULLSCREEN)
    pygame.display.set_caption('#HJ Game Engine Initializing...')
    self.poll = 0
    self.quit = 0
    # Boolean that holds if the size of the display screen has changed
    self.scalechanged = True
    # THis holds if the game is running in either debug mode, set by Main
    self.debugstates = (False, False)
    self.count = 0
    self.mapfollow = False
    # the speed of the physics simulation per step
    self.physicsstep = 90

    # Modes:
    # 0 = Main Menu
    # 1 = Game
    # 2 = New Game
    # 3 = Load Game
    # 4 = Options Menu
    # 5 = Pause Screen
    # 6 = Developer Console
    # 7 = Updater
    # 8 = Return to previous mode
    # 9 = LOLMINIGAME 1
    self.mode = 0
    self.prevmode = 0
    # List of named modes, for debug screen
    self.modes = ['Main Menu', 'Game', 'New Game', 'Load Game', 'Options Menu', 'Pause', 'Console', 'Updater', 'Previous', 'Minigame 1']

    # Create debug class
    self.debug = debug.Debug(False, self.preS, (5,5), (5,5), 4, __version__)

    # MINIGAME CLASS
    self.minigame = minigame.MiniGame(self.common, self.debug)

    # LENGTH OF A 'DAY' IN MINUTES:
    self.daylength = 5
    # TIME BETWEEN SCHEDULED TASKS:
    self.taskdelay = 1

    # STARFIELD INIT
    self.starfield = stars.starfield()
    # (255,210,210) redish
    # (210,210,255) blueish
    # (255,255,210) yellowish
    star_sample = [(255,220,220,1),(255,255,255,2),(220,220,255,1),(255,255,220,1),\
      (255,220,220,2),(255,255,255,2),(255,255,255,3),(255,255,255,3),(255,255,255,2), \
      (255,255,255,1),(255,255,255,1),(255,255,255,1),(255,255,255,1),(255,255,255,1), \
      (255,210,210,2),(255,255,255,2),(255,255,255,3),(255,255,255,3),(255,255,255,2), \
      (255,255,255,1),(255,255,255,1),(255,255,255,2),(255,255,255,2),(255,255,255,2) ]
    self.starfield.add_layer(50, .25, "down", star_sample, self.common.initsize)
    self.starfield.add_layer(100, .5, "down", star_sample, self.common.initsize)
    self.starfield.add_layer(100, .75, "down", star_sample, self.common.initsize)
    self.starfield.add_layer(100, 1, "down", star_sample, self.common.initsize)
    self.starfield.add_layer(100, 1.25, "down", star_sample, self.common.initsize)

  def newGame(self):
    """ Creates a WHOLE NEW GAME! :O """

    # Create new instance of world class
    self.world = world.World(self.gameS)
    # initiate renderer
##    self.renderer = renderer.Renderer()
##    self.world.loadMap('space', self.screen)
####    self.world.initPymunk(self.screen)
##    self.renderer.load(self.world.currentmap, self.common.initsize)
    logging.info('New game created')


  def postInit(self):
    """ This is a work around method for loading sounds and such after using pygame.movie
    to play the splash screens. """

    self.common.settings.activate()
    self.sound = sound.effect('resources/config/sounds.ini', self.debug)
    self.music = sound.music('resources/config/sounds.ini', self.debug)
    self.menu = menu.Menu(self.menuS, 'menu.ini', self.common, self.sound, self.music, self.debug)
    self.options = options.Options(self.optionS, 'options.ini', self.common, self.sound, self.music, self.debug, self.size)
    # Pause Screen class
    self.pause = pause.Pause('pause.ini', self.common, self.sound, self.music, self.debug)

  def setMode(self, mode):
    """ Used to change the game's mode.
    Same as using game.mode = x """
    if self.mode != 8:
      if self.prevmode != mode and mode != self.mode:
        self.prevmode = self.mode
    self.mode = mode

  def usePrevMode(self):
    self.mode = self.prevmode
##    self.setMode(self.prevmode)
##    self.setMode(self.prevmode)

  def checkQuit(self):
    if self.quit == 1:
      return True
    else:
      return False

  def updatePreS(self, surface):

    # Draws the game to the main screen
    if surface.get_size() != self.screen.get_size():
      pygame.transform.smoothscale(surface, self.size, self.preS)
    else:
      self.preS.blit(surface, (0,0))

  def saveWorld(self, savename, load=True):
    """ PERMADEATH OR BUST, DO NOT USE THIS EVER """
    self.world.savename = savename
    tempsprites = self.world.imagehandler.sprites
    self.world.imagehandler.reset()
    self.world.removePymunk(self.screen)
    filename = 'Saves'
    f = open(os.path.join(filename, self.world.savename + '.hjsav'), 'wb')
    object1 = zlib.compress(cPickle.dumps(self.world, cPickle.HIGHEST_PROTOCOL),9)
    cPickle.dump(object1,f,cPickle.HIGHEST_PROTOCOL)
    f.close()
    self.world.imagehandler.sprites = tempsprites

    logging.info('Game %s saved', savename)
    if load == True:
      self.loadSave(savename)
##    self.world.loadPhysics(self.screen)
##    self.world.initPymunk(self.screen)

  def loadSave(self, savename):
    """ LOAD A SAVE LOLOL """
    filename = 'Saves'
    try:
      f = open(os.path.join(filename, savename + '.hjsav'),'rb')
      obj = cPickle.load(f)
      self.world = cPickle.loads(zlib.decompress(obj))
      f.close()
    except IOError as e:
      logging.critical('Failed to load save %s' % savename)

    # This makes the world reload the map, instead of using the one in memory, in case map
    # files were updated
    self.world.loadMap(self.world.currentmapname, self.screen)
    # Let the render load up the correct map
##    self.world.initPymunk(self.screen)
    self.renderer = renderer.Renderer()
    self.renderer.load(self.world.currentmap, self.common.initsize)
    self.world.createCollisionBodies(self.screen)
    # Reset camera pos to previous position
    self.renderer.moveCamera(self.world.camerapos)
    logging.info('Game %s loaded', savename)


  def changeMap(self, mapname, savename):
    """ Change map being used by the world and renderer"""
    self.saveWorld(savename, load=False)
    self.world.removePymunk(self.screen)
    self.world.loadMap(mapname, self.screen)
    self.world.camerapos = (0,0)
##    self.world.initPymunk(self.screen)
    self.renderer.load(self.world.currentmap, self.common.initsize)
    self.world.createCollisionBodies(self.screen)
    logging.info('Changed map to %s', mapname)


#-------------------------------------------------------------------------------
#--------------------------------- Game Loop -----------------------------------
#-------------------------------------------------------------------------------


  def runGame(self, time):

    self.common.time = time

    self.gameS.fill((0,0,0))

    # self.world.runningtime is the length of time the gamemode has been running in seconds
    self.world.runningtime += (time / 1000.0)


    # Controls music queue
##    if self.music.getCurrentLoop() != self.world.currentmap.properties['music']:
##      self.music.loadQueue(self.world.currentmap.properties['music'])
##      self.music.playQueue()
##    if pygame.mixer.music.get_busy() == 0:
##      self.music.playQueue()

#-------------------------------------------------------------------------------

    key = pygame.key.get_pressed()

    # Bring up puase screen
    if self.pause.gamecount > 10:
      if key[self.common.key.bind['pause']]:
        self.setMode(5)
    self.pause.gamecount += 1

#-------------------------------------------------------------------------------

    # Move test player
    tempx,tempy = 0,0
    impulse = (0,0)
    if key[self.common.key.bind['up']]:
      self.world.player.move((0,-2))
    if key[self.common.key.bind['down']]:
      self.world.player.move((0,2))
    if key[self.common.key.bind['left']]:
      self.world.player.move((-2,0))
    if key[self.common.key.bind['right']]:
      self.world.player.move((2,0))


    # Temporary function key stuff
    if key[pygame.K_F1]:
      self.mode = 9
##    if key[pygame.K_F2]:
##      self.loadSave('1')
##    if key[pygame.K_F6]:
##      if self.mapfollow:
##        self.mapfollow = False
##      else:
##        self.mapfollow = True
##    if key[pygame.K_F10]:
##      self.bullettime = True


    self.world.updateCollisions()

    # DRAW STARFIELD
    self.starfield.draw(self.gameS)

    # DRAW SHIP
    self.gameS.blit(self.world.imagehandler.getSprite('ship.png'), self.world.shippos)
    self.world.stations.draw(self.gameS)

    self.world.player.checkInRange(self.world.stations)

    # Draw Player
    self.world.player.draw(self.gameS)
##    for tile in self.world.tilelist:
##      pygame.draw.rect(self.gameS, (255,0,0), tile.rect)



